#include <linux/skbuff.h>

#include "rxe.h"
#include "rxe_loc.h"
#include "rxe_queue.h"

enum resp_states {
    RESPST_NONE,//0
    RESPST_GET_REQ,//1
    RESPST_CHK_PSN,//2
    RESPST_CHK_OP_SEQ,//3
    RESPST_CHK_OP_VALID,//4
    RESPST_CHK_RESOURCE,//5
    RESPST_CHK_LENGTH,//6
    RESPST_CHK_RKEY,//7
    RESPST_EXECUTE,//8
    RESPST_READ_REPLY,//9
    RESPST_COMPLETE,//10
    RESPST_ACKNOWLEDGE,//11
    RESPST_CLEANUP,//12
    RESPST_DUPLICATE_REQUEST,//13
    RESPST_ERR_MALFORMED_WQE,//14
    RESPST_ERR_UNSUPPORTED_OPCODE,//15
    RESPST_ERR_MISALIGNED_ATOMIC,//16
    RESPST_ERR_PSN_OUT_OF_SEQ,//17
    RESPST_ERR_MISSING_OPCODE_FIRST,//18
    RESPST_ERR_MISSING_OPCODE_LAST_C,//19
    RESPST_ERR_MISSING_OPCODE_LAST_D1E,//20
    RESPST_ERR_TOO_MANY_RDMA_ATM_REQ,//21
    RESPST_ERR_RNR,//22
    RESPST_ERR_RKEY_VIOLATION,//23
    RESPST_ERR_INVALIDATE_RKEY,//24
    RESPST_ERR_LENGTH,//25
    RESPST_ERR_CQ_OVERFLOW,//26
    RESPST_ERROR,//27
    RESPST_RESET,//28
    RESPST_DONE,//29
    RESPST_EXIT,//30
};

static char *resp_state_name[] = {
    [RESPST_NONE]               = "NONE",
    [RESPST_GET_REQ]            = "GET_REQ",
    [RESPST_CHK_PSN]            = "CHK_PSN",
    [RESPST_CHK_OP_SEQ]         = "CHK_OP_SEQ",
    [RESPST_CHK_OP_VALID]       = "CHK_OP_VALID",
    [RESPST_CHK_RESOURCE]       = "CHK_RESOURCE",
    [RESPST_CHK_LENGTH]         = "CHK_LENGTH",
    [RESPST_CHK_RKEY]           = "CHK_RKEY",
    [RESPST_EXECUTE]            = "EXECUTE",
    [RESPST_READ_REPLY]         = "READ_REPLY",
    [RESPST_COMPLETE]           = "COMPLETE",
    [RESPST_ACKNOWLEDGE]        = "ACKNOWLEDGE",
    [RESPST_CLEANUP]            = "CLEANUP",
    [RESPST_DUPLICATE_REQUEST]  = "DUPLICATE_REQUEST",
    [RESPST_ERR_MALFORMED_WQE]  = "ERR_MALFORMED_WQE",
    [RESPST_ERR_UNSUPPORTED_OPCODE] = "ERR_UNSUPPORTED_OPCODE",
    [RESPST_ERR_MISALIGNED_ATOMIC]  = "ERR_MISALIGNED_ATOMIC",
    [RESPST_ERR_PSN_OUT_OF_SEQ] = "ERR_PSN_OUT_OF_SEQ",
    [RESPST_ERR_MISSING_OPCODE_FIRST] = "ERR_MISSING_OPCODE_FIRST",
    [RESPST_ERR_MISSING_OPCODE_LAST_C] = "ERR_MISSING_OPCODE_LAST_C",
    [RESPST_ERR_MISSING_OPCODE_LAST_D1E] = "ERR_MISSING_OPCODE_LAST_D1E",
    [RESPST_ERR_TOO_MANY_RDMA_ATM_REQ] = "ERR_TOO_MANY_RDMA_ATM_REQ",
    [RESPST_ERR_RNR] = "ERR_RNR",
    [RESPST_ERR_RKEY_VIOLATION] = "ERR_RKEY_VIOLATION",
    [RESPST_ERR_INVALIDATE_RKEY] = "ERR_INVALIDATE_RKEY_VIOLATION",
    [RESPST_ERR_LENGTH]         = "ERR_LENGTH",
    [RESPST_ERR_CQ_OVERFLOW]    = "ERR_CQ_OVERFLOW",
    [RESPST_ERROR]              = "ERROR",
    [RESPST_RESET]              = "RESET",
    [RESPST_DONE]               = "DONE",
    [RESPST_EXIT]               = "EXIT",
};

void rxe_resp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
{
    int must_sched;

    struct rxe_pkt_info *pkt = SKB_TO_PKT(skb);

    /*将收到的skb加到队列尾部*/
    skb_queue_tail(&qp->req_pkts, skb);

    /*如果是read请求或者skb的数量大于1,就以调度的形式调度回调函数*/
    must_sched = (pkt->opcode == IB_OPCODE_RC_RDMA_READ_REQUEST) ||
        (skb_queue_len(&qp->req_pkts) > 1);

    rxe_run_task(&qp->resp.task, must_sched);
}

static inline enum resp_states get_req(struct rxe_qp *qp,
        struct rxe_pkt_info **pkt_p)
{

}

static enum resp_states check_psn(struct rxe_qp *qp,
        struct rxe_pkt_info *pkt)
{


}

static enum resp_states check_op_seq(struct rxe_qp *qp,
        struct rxe_pkt_info *pkt)
{


}

static enum resp_states check_op_valid(struct rxe_qp *qp,
        struct rxe_pkt_info *pkt)
{


}

static enum resp_states get_srq_wqe(struct rxe_qp *qp)
{

}

static enum resp_states check_resource(struct rxe_qp *qp,
        struct rxe_pkt_info *pkt)
{

}

static enum resp_states check_length(struct rxe_qp *qp,
        struct rxe_pkt_info *pkt)
{


}

static enum resp_states check_rkey(struct rxe_qp *qp,
        struct rxe_pkt_info *pkt)
{


}

static enum resp_states send_data_in(struct rxe_qp *qp, void *data_addr,
        int data_len)
{

}

static enum resp_states write_data_in(struct rxe_qp *qp,
        struct rxe_pkt_info *pkt)
{


}

static DEFINE_SPINLOCK(atomic_ops_lock);

static enum resp_states process_atomic(struct rxe_qp *qp,
        struct rxe_pkt_info *pkt)
{



}

static struct sk_buff *prepare_ack_packet(struct rxe_qp *qp,
        struct rxe_pkt_info *pkt, struct rxe_pkt_info *ack,
        int opcode, int payload, u32 psn, u8 syndrome)
{
    struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
    struct sk_buff *skb;
    int err, pad, paylen;

    pad = (-payload) & 0x3; //icrc校验4字节对齐
    //BTH头开始的长度
    paylen = rxe_opcode[opcode].length + payload + pad + RXE_ICRC_SIZE;
    skb = rxe_init_packet(rxe, &qp->pri_av, paylen, ack);

    /*输出参数*/
    ack->qp = qp;
    ack->opcode = opcode;
    ack->mask = rxe_opcode[opcode].mask;
    ack->paylen = paylen;
    ack->psn = psn;

    /*BTH头字段初始化*/
    bth_init(ack, opcode, 0, 0, pad, IB_DEFAULT_PKEY_FULL,
        qp->attr.dest_qp_num, 0, psn);

    /*加上ACK扩展头*/
    if(ack->mask & RXE_AETH_MASK) {
        aeth_set_syn(ack, syndrome);
        aeth_set_msn(ack, qp->resp.msn);
    }

    /*加上ATOMIC Ack 扩展头*/
    if (ack->mask & RXE_ATMACK_MASK) {
        atmack_set_orig(ack, qp->resp.atomic_orig);
    }

    /*设置L2,L3,L4字段值*/
    err = rxe_prepare(ack, skb);
    if(err) {
        kfree_skb(skb);
        return NULL;
    }
    return skb;
}

static enum resp_states read_reply(struct rxe_qp *qp,
        struct rxe_pkt_info *req_pkt)
{

}

static int invalidate_rkey(struct rxe_qp *qp, u32 rkey)
{

}

static enum resp_states execute(struct rxe_qp *qp, struct rxe_pkt_info *pkt)
{


}

static enum resp_states do_complete(struct rxe_qp *qp,
        struct rxe_pkt_info *pkt)
{


}

static int send_ack(struct rxe_qp *qp, struct rxe_pkt_info *pkt,
        u8 syndrome, u32 psn)
{
    int err;
    struct rxe_pkt_info ack_pkt;
    struct sk_buff *skb;

    /*构造一个ack包*/
    skb = prepare_ack_packet(qp, pkt, &ack_pkt, IB_OPCODE_RC_ACKNOWLEDGE,
             0, psn, syndrome);
    if(!skb) {
        err = -ENOMEM;
        goto err;
    }

    /*调用发送接口*/
    err = rxe_xmit_packet(qp, &ack_pkt, skb);
    if(err)
        pr_err_ratelimited("Failed sending ack\n");
err:
    return err;
}

static int send_atomic_ack(struct rxe_qp *qp, struct rxe_pkt_info *pkt,
        u8 syndrome)
{
    int rc;

    return rc;

}

/*回复ack包*/
static enum resp_states acknowledge(struct rxe_qp *qp,
        struct rxe_pkt_info *pkt)
{
    /*只有QP类型为RC的才会回复ack包*/
    if (qp_type(qp) != IB_QPT_RC)
        return RESPST_CLEANUP;




}

static enum resp_states cleanup(struct rxe_qp *qp,
        struct rxe_pkt_info *pkt)
{



}

static enum resp_states duplicate_request(struct rxe_qp *qp,
     struct rxe_pkt_info *pkt)
{

}

static void do_class_ac_error(struct rxe_qp *qp, u8 syndrome,
        enum ib_wc_status status)
{

}

static enum resp_states do_class_d1e_error(struct rxe_qp *qp)
{


}

static enum resp_states do_class_d1e_error(struct rxe_qp *qp)
{


}

static void rxe_drain_req_pkts(struct rxe_qp *qp, bool notify)
{



}

int rxe_responder(void *arg)
{
    struct rxe_qp *qp = (struct rxe_qp *)arg;
    struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
    enum resp_states state;
    struct rxe_pkt_info *pkt = NULL;
    int ret = 0;

    rxe_add_ref(qp);

    qp->resp.aeth_syndrome = AETH_ACK_UNLIMITED;

    if (!qp->valid) {
        ret = -EINVAL;
        goto done;
    }




exit:
    ret = -EAGAIN;
done:
    rxe_drop_ref(qp);
    return ret;
}

